﻿using System;
using System.Collections.Generic;
using System.IO;
using Loki.Utils;

namespace Luna.Connectors.ZohoCRM
{
    public class ZohoEntityContext<T> : LokiObject where T : ZohoEntity
    {
        public ZohoEntityContext(ZohoCrmClient P_Client)
        {
            Client = P_Client;
        }

        protected ZohoCrmClient Client { get; private set; }

        public T GetById(string P_ID)
        {
            return Client.GetRecordById<T>(P_ID);
        }

        public T RequireById(string P_ID)
        {
            var L_Entity = GetById(P_ID);
            if (L_Entity == null)
            {
                throw BuildErrorFormat<ArgumentException>(Resources.Errors.INVALID_ID, typeof(T), P_ID);
            }

            return L_Entity;
        }

        public ZohoEntityCollection<T> List(ListOptions P_Options)
        {
            return Client.GetRecords<T>(P_Options);
        }

        public ZohoEntityCollection<T> ListMy(ListOptions P_Options)
        {
            return Client.GetMyRecords<T>(P_Options);
        }

        public ZohoEntityCollection<TRelated> ListRelated<TRelated>(string P_ID) where TRelated : ZohoEntity
        {
            return Client.GetRelatedRecordsTo<T, TRelated>(P_ID);
        }

        public ZohoEntityCollection<ZohoAttachment> ListAttachments(string P_ID)
        {
            return ListRelated<ZohoAttachment>(P_ID);
        }

        public ZohoInsertResponse Insert(T P_Record)
        {
            return Client.InsertRecord(P_Record);
        }

        public ZohoInsertResponse Insert(IEnumerable<T> P_Records)
        {
            return Client.InsertRecords(P_Records);
        }

        public bool Delete(T P_Record)
        {
            return Client.DeleteRecord(P_Record);
        }

        public bool DeleteById(string P_ID)
        {
            return Client.DeleteRecordById<T>(P_ID);
        }

        public bool Update(T P_Record)
        {
            return Client.UpdateRecord(P_Record);
        }

        public string UploadFile(string P_ID, string P_FileName, string P_ContentType, byte[] P_Bytes)
        {
            return Client.UploadFileToRecord<T>(P_ID, P_FileName, P_ContentType, P_Bytes);
        }

        public string UploadFile(string P_ID, string P_FileName, string P_ContentType, Stream P_InputStream)
        {
            return Client.UploadFileToRecord<T>(P_ID, P_FileName, P_ContentType, P_InputStream);
        }

        public string UploadFile(string P_ID, string P_FileName, string P_ContentType, Uri P_Uri)
        {
            return Client.UploadFileToRecord<T>(P_ID, P_FileName, P_ContentType, P_Uri);
        }

        public string UploadFile(string P_ID, string P_FileName, string P_ContentType, string P_FilePath)
        {
            return Client.UploadFileToRecord<T>(P_ID, P_FileName, P_ContentType, P_FilePath);
        }

        public string UploadPhoto(string P_ID, string P_ContentType, byte[] P_Bytes)
        {
            return Client.UploadPhotoToRecord<T>(P_ID, P_ContentType, P_Bytes);
        }

        public string UploadPhoto(string P_ID, string P_ContentType, Stream P_InputStream)
        {
            return Client.UploadPhotoToRecord<T>(P_ID, P_ContentType, P_InputStream);
        }

        public string UploadPhoto(string P_ID, string P_ContentType, Uri P_Uri)
        {
            return Client.UploadPhotoToRecord<T>(P_ID, P_ContentType, P_Uri);
        }

        public string UploadPhoto(string P_ID, string P_ContentType, string P_FilePath)
        {
            return Client.UploadPhotoToRecord<T>(P_ID, P_ContentType, P_FilePath);
        }

        public ZohoEntityCollection<T> Search(ZohoSearchCondition P_Condition)
        {
            return Search(P_Condition, null);
        }

        public ZohoEntityCollection<T> Search(ZohoSearchCondition P_Condition, IEnumerable<string> P_Columns)
        {
            return Client.Search<T>(P_Condition, P_Columns);
        }

        public ZohoEntityCollection<T> Search(string P_Column, ConditionOperator P_Operator, object P_Value)
        {
            return Search(new ZohoSearchCondition(P_Column, P_Operator, P_Value));
        }

        public ZohoEntityCollection<T> ElementIs(string P_Column, object P_Value)
        {
            return Search(P_Column, ConditionOperator.Is, P_Value);
        }

        public ZohoEntityCollection<T> IsNot(string P_Column, object P_Value)
        {
            return Search(P_Column, ConditionOperator.IsNot, P_Value);
        }

        public ZohoEntityCollection<T> GreaterThan(string P_Column, object P_Value)
        {
            return Search(P_Column, ConditionOperator.GreaterThan, P_Value);
        }

        public ZohoEntityCollection<T> LesserThan(string P_Column, object P_Value)
        {
            return Search(P_Column, ConditionOperator.LesserThan, P_Value);
        }

        public ZohoEntityCollection<T> GreaterOrEqualThan(string P_Column, object P_Value)
        {
            return Search(P_Column, ConditionOperator.GreaterOrEqualThan, P_Value);
        }

        public ZohoEntityCollection<T> LesserOrEqualThan(string P_Column, object P_Value)
        {
            return Search(P_Column, ConditionOperator.LesserOrEqualsThan, P_Value);
        }

        public ZohoEntityCollection<T> Contains(string P_Column, string P_Value)
        {
            return Search(P_Column, ConditionOperator.Contains, P_Value);
        }

        public ZohoEntityCollection<T> NotContains(string P_Column, string P_Value)
        {
            return Search(P_Column, ConditionOperator.NotContains, P_Value);
        }

        public ZohoEntityCollection<T> StartsWith(string P_Column, string P_Value)
        {
            return Search(P_Column, ConditionOperator.StartsWith, P_Value);
        }

        public ZohoEntityCollection<T> EndsWith(string P_Column, string P_Value)
        {
            return Search(P_Column, ConditionOperator.EndsWith, P_Value);
        }

        public DownloadFile DownloadFile(string P_ID)
        {
            return Client.DownloadRecordFile<T>(P_ID);
        }
    }
}